package holdem;

//Hand Holds Card and Eval wich is better
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class Hand {
    private ArrayList<Card> inHand = new ArrayList<Card>();

    //~--- methods ------------------------------------------------------------

    // matches by suit then number

    public Hand(Card[] cards) {
        inHand.addAll(Arrays.asList(cards));
    }
    public Hand(List<Card> cards) {
        inHand.addAll(cards);
    }
    public Hand() {
        
    }

    private int[] getNumberBuctet() {
	int[] bucket = new int[13];

	for (int i = 0; i < inHand.size(); i++) {
	    bucket[inHand.get(i).getValue()-1]++;
	}

	return bucket;
    }

    private int[] getSuitBuctet() {
	int[] bucket = new int[5];

	for (int i = 0; i < inHand.size(); i++) {
	    bucket[inHand.get(i).getSuiteInt()-1]++;
	}

	return bucket;
    }

    void addCard(Card c) {
	inHand.add(c);
    }

    void empty() {
	inHand = new ArrayList<Card>();
    }

    boolean pair() {
	int bucket[] = new int[13];

	for (int i = 0; i < inHand.size(); i++) {
	    bucket[inHand.get(i).getValue()-1]++;
	}

	for (int i = 0; i < bucket.length; i++) {
	    if (bucket[i] > 1) {
		return true;
	    }

	}

	return false;
    }

    boolean twoPair() {
	int bucket[] = new int[13];

	for (int i = 0; i < inHand.size(); i++) {
	    bucket[inHand.get(i).getValue()-1]++;
	}

	int j = 0;

	for (int i = 0; i < bucket.length; i++) {

	    if (bucket[i] > 1) {
		j++;
	    }

	    if (j > 1) {
		return true;
	    }

	}

	return false;
    }

    boolean threeKind() {
	int bucket[] = new int[13];

	for (int i = 0; i < inHand.size(); i++) {
	    bucket[inHand.get(i).getValue()-1]++;
	}

	int j = 0;

	for (int i = 0; i < bucket.length; i++) {

	    if (bucket[i] > 2) {
		return true;
	    }


	}

	return false;
    }

    boolean fourKind() {
	int bucket[] = new int[13];

	for (int i = 0; i < inHand.size(); i++) {
	    bucket[inHand.get(i).getValue()-1]++;
	}

	for (int i = 0; i < bucket.length; i++) {

	    if (bucket[i] > 3) {
		return true;
	    }


	}

	return false;
    }

    boolean fullHouse() {
	int bucket[] = new int[13];

	for (int i = 0; i < inHand.size(); i++) {
	    bucket[inHand.get(i).getValue()-1]++;
	}

	int j = 0;
	int k = 0;

	for (int i = 0; i < bucket.length; i++) {
	    if (bucket[i] > 2) {
		j++;

		continue;
	    }

	    if (bucket[i] > 1) {
		k++;
	    }
	}

	return ((j > 1) || ((j > 0) && (k > 0)));
    }

    boolean strait() {
	int bucket[] = new int[14];

	for (int i = 0; i < inHand.size(); i++) {
	    bucket[inHand.get(i).getValue()-1]++;
            if(inHand.get(i).getValue() == 1) {
                // add high Ace
                bucket[13]++;
            }
	}

	int j = 0;

	for (int i = 0; i < bucket.length; i++) {
	    if (bucket[i] > 0) {
		j++;
	    }

	    if (j > 4) {
		return true;
	    }

	    if (bucket[i] == 0) {
		j = 0;
	    }
	}

	return false;
    }

    boolean flush() {
	int bucket[] = new int[5];

	for (int i = 0; i < inHand.size(); i++) {
	    bucket[inHand.get(i).getSuiteInt()]++;
	}

	for (int i = 0; i < bucket.length; i++) {
	    if (bucket[i] > 4) {
		return true;
	    }
	}

	return false;
    }

    boolean straitflush() {
	return flush() && strait();
    }

    boolean royalFlush() {
	int bucket[] = new int[14];

	if (!flush()) {
	    return false;
	}

	for (int i = 0; i < inHand.size(); i++) {
	    bucket[inHand.get(i).getValue()-1]++;
            if(inHand.get(i).getValue() == 1) {
                // add high Ace
                bucket[13]++;
            }
	}

	int count = 0;

	for (int i = 10; i < bucket.length; i++) {
	    if (bucket[i] > 0) {
		count++;

		continue;
	    } else {
		return false;
	    }
	}

	return true;
    }

    public HandTypes BestHand() {
	if (royalFlush()) {
	    return HandTypes.RFLUSH;
	}

	if (straitflush()) {
	    return HandTypes.STRIATFLUSH;
	}

	if (fourKind()) {
	    return HandTypes.FOURKIND;
	}

	if (fullHouse()) {
	    return HandTypes.FULLHOUSE;
	}

	if (flush()) {
	    return HandTypes.FLUSH;
	}

	if (strait()) {
	    return HandTypes.STRAIT;
	}

	if (threeKind()) {
	    return HandTypes.THREEKIND;
	}

	if (twoPair()) {
	    return HandTypes.TWOPAIR;
	}

	if (pair()) {
	    return HandTypes.PAIR;
	}

	return HandTypes.HIGHCARD;
    }
}
